package com.sikaryofficial.backend.service.address;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Lists;
import com.sikaryofficial.backend.constant.RedisCacheKey;
import com.sikaryofficial.backend.domain.dto.req.AddressAreaReq;
import com.sikaryofficial.backend.domain.dto.req.AddressCityReq;
import com.sikaryofficial.backend.domain.dto.req.AddressListReq;
import com.sikaryofficial.backend.domain.entity.Address;
import com.sikaryofficial.backend.domain.mapping.AddressMapping;
import com.sikaryofficial.backend.service.IAddressService;
import com.sikaryofficial.common.redis.service.RedisService;
import com.sikaryofficial.system.api.model.AddressDTO;
import io.jsonwebtoken.lang.Collections;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.stream.Collectors;

/**
 * @author : qinjinyuan
 * @desc : 指标统计缓存服务
 * @date : 2023/11/03 17:11
 */
@Component
@Slf4j
public class AddressCacheService {
    @Autowired
    private IAddressService addressService;
    @Value("${hismk.backend.defaultCountry}")
    private String defaultCountry;
    @Autowired
    private RedisService redisService;
    /**
     * 获取所有地址
     *
     * @return
     */
    public List<AddressDTO> getAllAddressByCountry() {
        Map<String, AddressDTO> addressDTOMap = redisService.getAllCacheMapByKey(buildCacheKeyWithCountry(defaultCountry));
        return new ArrayList<>(addressDTOMap.values());
    }

    public List<AddressDTO> getAllAddressByCountry(String country) {
        if (CharSequenceUtil.isBlank(country)) {
            return Lists.newArrayList();
        }
        Map<String, AddressDTO> addressDTOMap = redisService.getAllCacheMapByKey(buildCacheKeyWithCountry(country));
        return new ArrayList<>(addressDTOMap.values());
    }

    /**
     * 地址列表 (数据预加载)
     *
     * @return
     */
    public void loadAllAddress() {
        List<Address> areaList = addressService.list(new LambdaQueryWrapper<Address>()
                .select(Address::getArea, Address::getCity, Address::getCounty, Address::getAddressId
                        , Address::getCountry, Address::getCountyDiscard, Address::getMd5)
                .eq(Address::getDeletedVersion, 0L)
        );
        if (Collections.isEmpty(areaList)) {
            return;
        }
        // 清除国家缓存列表
        redisService.deleteObject(RedisCacheKey.ADDRESS_COUNTRY_LIST_CACHE);
        // 清除国家缓存对应的集合
        Collection<String> collKeys = redisService.keys(RedisCacheKey.ADDRESS_ALL_LIST_CACHE + "*");
        redisService.deleteObject(collKeys);
        List<AddressDTO> areaListCache = AddressMapping.INSTANCE.coverListToResp(areaList);
        log.info("load address size :{}", areaListCache.size());
        Set<String> countrySet = new HashSet<>();
        areaListCache.stream().filter(addressDTO -> CharSequenceUtil.isNotBlank(addressDTO.getCountry())).forEach(addressDTO -> {
            countrySet.add(addressDTO.getCountry());
            String cacheKey = buildCacheKeyWithCountry(addressDTO.getCountry());
            redisService.setCacheMapValue(cacheKey, String.valueOf(addressDTO.getAddressId()), addressDTO);
        });
        redisService.setCacheSet(RedisCacheKey.ADDRESS_COUNTRY_LIST_CACHE, countrySet);
    }

    public List<String> countryList() {
        Set<String> countrySet = redisService.getCacheSet(RedisCacheKey.ADDRESS_COUNTRY_LIST_CACHE);
        if (CollUtil.isEmpty(countrySet)) {
            return Lists.newArrayList();
        }
        return countrySet.stream().sorted(Comparator.comparing(String::toString)).collect(Collectors.toList());
    }

    /**
     * 区域列表
     *
     * @return
     */
    public List<String> areaList(AddressAreaReq req) {
        String country ;
        if(Objects.isNull(req) || CharSequenceUtil.isBlank(req.getCountry())){
            country = defaultCountry;
        }else{
            country = req.getCountry();
        }
        List<AddressDTO> addressDTOS = getAllAddressByCountry(country);
        if (CollUtil.isEmpty(addressDTOS)) {
            return new ArrayList<>();
        }
        return addressDTOS.stream().map(AddressDTO::getArea)
                .filter(CharSequenceUtil::isNotBlank).distinct().sorted(Comparator.comparing(String::toString)).collect(Collectors.toList());
    }

    public List<String> cityList(AddressCityReq req) {
        List<AddressDTO> addressDTOS = getAllAddressByCountry(CharSequenceUtil.isNotBlank(req.getCountry()) ? req.getCountry() : defaultCountry);
        if (CollUtil.isEmpty(addressDTOS) || CharSequenceUtil.isBlank(req.getArea())) {
            return new ArrayList<>();
        }
        return addressDTOS.stream().filter(addressDTO ->  CharSequenceUtil.isNotBlank(addressDTO.getArea())
                        && addressDTO.getArea().equals(req.getArea())
                        && CharSequenceUtil.isNotBlank(addressDTO.getCity()))
                .map(AddressDTO::getCity).distinct().sorted(Comparator.comparing(String::toString)).collect(Collectors.toList());
    }

    public List<AddressDTO> getAddressListByParam(AddressListReq req) {
        List<AddressDTO> addressDTOS = getAllAddressByCountry(CharSequenceUtil.isNotBlank(req.getCountry()) ? req.getCountry() : defaultCountry);
        if (CollUtil.isEmpty(addressDTOS) || CharSequenceUtil.isBlank(req.getArea())) {
            return new ArrayList<>();
        }
        addressDTOS = addressDTOS.stream().filter(addressDTO ->
                                CharSequenceUtil.isNotBlank(addressDTO.getArea())
                                 && addressDTO.getArea().equals(req.getArea()))
                .filter(addressDTO -> addressDTO.getCity().equals(req.getCity()))
                .sorted(Comparator.comparing(AddressDTO::getCounty)).collect(Collectors.toList());
        if (CharSequenceUtil.isNotBlank(req.getCountry())) {
            addressDTOS = addressDTOS.stream().filter(addressDTO ->
                            CharSequenceUtil.isNotBlank(addressDTO.getCountry())
                            && addressDTO.getCountry().equals(req.getCountry()))
                    .collect(Collectors.toList());
        }
        // 对区县进行模糊匹配
        if (CharSequenceUtil.isNotBlank(req.getKeyword())) {
            addressDTOS = addressDTOS.stream().filter(item -> CharSequenceUtil.isNotBlank(item.getCountry())
                    && item.getCounty().startsWith(req.getKeyword())).collect(Collectors.toList());
        }
        return addressDTOS;
    }

    public SortedMap<String, String> cityMap(AddressCityReq req) {
        String area = req.getArea();
        String cacheKey = buildCacheKeyWithCountry(CharSequenceUtil.isNotBlank(req.getCountry()) ? req.getCountry() : defaultCountry);
        Map<String, AddressDTO> data = redisService.getAllCacheMapByKey(cacheKey);
        TreeMap<String, String> cityListCache = new TreeMap<>();
        data.forEach((key, value) -> {
            if (value.getArea().equals(area)) {
                if (cityListCache.containsKey(value.getCity())) {
                    cityListCache.put(value.getCity(), cityListCache.get(value.getCity()) + "," + key);
                } else {
                    cityListCache.put(value.getCity(), key);
                }
            }
        });
        return cityListCache;
    }

    private String buildCacheKeyWithCountry(String country) {
        return MessageFormat.format(RedisCacheKey.ADDRESS_ALL_LIST_CACHE, country);
    }

}
